home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / S3 / S3wgl.c < prev   
Encoding:
C/C++ Source or Header  |  1997-11-12  |  15.6 KB  |  630 lines

  1. /*
  2.  * s3wgl.c
  3.  *
  4.  * Originally from Mesa 3Dfx driver, rewritten and bugfixed
  5.  */
  6.  
  7. #ifdef S3
  8.  
  9. #ifdef __cplusplus
  10. extern "C" {
  11. #endif
  12.  
  13. #include <GL/gl.h>
  14. #include <GL/glu.h>
  15.  
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19.  
  20. #include <stdio.h>
  21. #include <windows.h>
  22.  
  23. #include "s3mesa.h"
  24.  
  25. #define _DLLEXPORT_                __declspec(dllexport)
  26. #define MAX_MESA_ATTRS    20
  27.  
  28. //#define DEBUG_WGL
  29.  
  30. struct __extensions__
  31. {
  32.     PROC    proc;
  33.     char    *name;
  34. };
  35.  
  36. struct __extensions__    ext[] = {
  37.  
  38. #ifdef GL_EXT_polygon_offset
  39.     {    (PROC)glPolygonOffsetEXT,        "glPolygonOffsetEXT"        },
  40. #endif
  41.     {    (PROC)glBlendEquationEXT,        "glBlendEquationEXT"        },
  42.     {    (PROC)glBlendColorEXT,            "glBlendColorExt"            },
  43.     {    (PROC)glVertexPointerEXT,        "glVertexPointerEXT"        },
  44.     {    (PROC)glNormalPointerEXT,        "glNormalPointerEXT"        },
  45.     {    (PROC)glColorPointerEXT,        "glColorPointerEXT"            },
  46.     {    (PROC)glIndexPointerEXT,        "glIndexPointerEXT"            },
  47.     {    (PROC)glTexCoordPointerEXT,        "glTexCoordPointer"            },
  48.     {    (PROC)glEdgeFlagPointerEXT,        "glEdgeFlagPointerEXT"        },
  49.     {    (PROC)glGetPointervEXT,            "glGetPointervEXT"            },
  50.     {    (PROC)glArrayElementEXT,        "glArrayElementEXT"            },
  51.     {    (PROC)glDrawArraysEXT,            "glDrawArrayEXT"            },
  52.     {    (PROC)glAreTexturesResidentEXT,    "glAreTexturesResidentEXT"    },
  53.     {    (PROC)glBindTextureEXT,            "glBindTextureEXT"            },
  54.     {    (PROC)glDeleteTexturesEXT,        "glDeleteTexturesEXT"        },
  55.     {    (PROC)glGenTexturesEXT,            "glGenTexturesEXT"            },
  56.     {    (PROC)glIsTextureEXT,            "glIsTextureEXT"            },
  57.     {    (PROC)glPrioritizeTexturesEXT,    "glPrioritizeTexturesEXT"    },
  58.     {    (PROC)glCopyTexSubImage3DEXT,    "glCopyTexSubImage3DEXT"    },
  59.     {    (PROC)glTexImage3DEXT,            "glTexImage3DEXT"            },
  60.     {    (PROC)glTexSubImage3DEXT,        "glTexSubImage3DEXT"        },
  61. };
  62. int                qt_ext = sizeof(ext) / sizeof(ext[0]);
  63.  
  64.  
  65.  
  66. /* See PIXELFORMATDESCRIPTOR in MSVC help */
  67.  
  68. struct __pixelformat__
  69. {
  70.     PIXELFORMATDESCRIPTOR    pfd;                        // The standard Windows DC pixelformat
  71.     GLint                    mesaAttr[MAX_MESA_ATTRS];    // The attributes that will be interpreted by the driver
  72. };
  73.  
  74. /* Our supported pixelformats; all reported as 32-bit */
  75. struct __pixelformat__    pix[] = 
  76. {
  77.     /* Depth cases must come before non-depth cases, so in the case of the application requesting
  78.      * a Z-buffer depth other than 16-bits one is still allocated even if it isn't as wide
  79.      * as that requested */
  80.  
  81.     /* With depth buffer, without double buffer */
  82.     {    {    sizeof(PIXELFORMATDESCRIPTOR),    1,
  83.             PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_SUPPORT_GDI,
  84.             PFD_TYPE_RGBA,
  85.             24,    8,    0,    8,    8,    8,    16,    8,    24,
  86.             8,    2,    2,    2,    2,    16,    8,    0,    0,    0,    0,    0,    0    },
  87.         {
  88.             S3MESA_ALPHA_SIZE,        8,
  89.             S3MESA_DEPTH_SIZE,        16,
  90.             S3MESA_STENCIL_SIZE,    8,
  91.             S3MESA_ACCUM_SIZE,        8,
  92.             S3MESA_NONE    }
  93.     },
  94.  
  95.     /* Without depth buffer and double buffer */
  96.     {    {    sizeof(PIXELFORMATDESCRIPTOR),    1,
  97.             PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_SUPPORT_GDI,
  98.             PFD_TYPE_RGBA,
  99.             24,    8,    0,    8,    8,    8,    16,    8,    24,
  100.             8,    2,    2,    2,    2,    0,    8,    0,    0,    0,    0,    0,    0    },
  101.         {
  102.             S3MESA_ALPHA_SIZE,        8,
  103.             S3MESA_DEPTH_SIZE,        0,
  104.             S3MESA_STENCIL_SIZE,    8,
  105.             S3MESA_ACCUM_SIZE,        8,
  106.             S3MESA_NONE    }
  107.     },
  108.  
  109.     /* With depth buffer & double buffer */
  110.     {    {    sizeof(PIXELFORMATDESCRIPTOR),    1,
  111.             PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_DOUBLEBUFFER|PFD_SUPPORT_GDI,
  112.             PFD_TYPE_RGBA,
  113.             24,    8,    0,    8,    8,    8,    16,    8,    24,
  114.             8,    2,    2,    2,    2,    16,    8,    0,    0,    0,    0,    0,    0    },
  115.         {
  116.             S3MESA_DOUBLEBUFFER,
  117.             S3MESA_ALPHA_SIZE,        8,
  118.             S3MESA_DEPTH_SIZE,        16,
  119.             S3MESA_STENCIL_SIZE,    8,
  120.             S3MESA_ACCUM_SIZE,        8,
  121.             S3MESA_NONE    }
  122.     },
  123.  
  124.     /* Without depth buffer, with double buffer */
  125.     {    {    sizeof(PIXELFORMATDESCRIPTOR),    1,
  126.             PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_DOUBLEBUFFER|PFD_SUPPORT_GDI,
  127.             PFD_TYPE_RGBA,
  128.             24,    8,    0,    8,    8,    8,    16,    8,    24,
  129.             8,    2,    2,    2,    2,    0,    8,    0,    0,    0,    0,    0,    0    },
  130.         {
  131.             S3MESA_DOUBLEBUFFER,
  132.             S3MESA_ALPHA_SIZE,        8,
  133.             S3MESA_DEPTH_SIZE,        0,
  134.             S3MESA_STENCIL_SIZE,    8,
  135.             S3MESA_ACCUM_SIZE,        8,
  136.             S3MESA_NONE    }
  137.     },
  138.  
  139. };
  140. int                qt_pix = sizeof(pix) / sizeof(pix[0]);        // Number of pixelformats in the driver
  141.  
  142.  
  143. static int                curPFD = 0;
  144.  
  145. #define MAX_CONTEXTS        32            // THIS MUST NOT BE CHANGED without redoing the MonitorProcs
  146.  
  147. /* This structure contains enough information to let us manage everything */
  148. typedef struct {
  149.     s3MesaContext    s3ctx;
  150.     HDC                hDC;
  151.     WNDPROC            hWNDOldProc;
  152.     HWND            hWND;
  153. } Contextlist;
  154. static Contextlist    ctxlist[MAX_CONTEXTS+1];
  155. static int    context_count = 0;                // Contexts allocated
  156. static int current_context = 0;                // Handle of the current context: 0 means no context
  157. static s3MesaContext    ctx = NULL;            // Current rendering context: NULL is no context
  158.  
  159.  
  160. #if 0
  161.  
  162. /*
  163.  * This monitors all the Windows messages that comes through, and performs any tasks that
  164.  * need to be done - particularly, resizes and moves in Windows mode.
  165.  */
  166. LONG APIENTRY __wglMonitor(HWND hwnd,UINT message,UINT wParam,LONG lParam)
  167. {
  168.     if (ctx && hwnd == hWND)
  169.     {
  170.         switch(message)
  171.         {
  172.             case WM_MOVE:
  173.                 s3MesaMoveWindow(ctx, lParam&0xffff, lParam>>16);
  174.                 break;
  175.  
  176.             case WM_DISPLAYCHANGE:
  177.             case WM_SIZE:
  178.                 s3MesaResizeWindow(ctx, lParam&0xffff, lParam>>16);
  179.                 break;
  180.  
  181.             case WM_ACTIVATE:
  182.                 /* In fullscreen mode, probably need to do something here */
  183.                 break;
  184.         }
  185.     }
  186.  
  187.     return(hWNDOldProc(hwnd,message,wParam,lParam));
  188. }
  189. #endif
  190.  
  191. #define MONITORPROC(a) \
  192. LONG APIENTRY __wglMonitor##a(HWND hwnd,UINT message,UINT wParam,LONG lParam) \
  193. {\
  194.     if (ctx && (ctx == ctxlist[a].s3ctx) && (hwnd == ctxlist[a].hWND)) {    \
  195.         switch(message) {        \
  196.         case WM_MOVE:            \
  197.             s3MesaMoveWindow(ctxlist[a].s3ctx, lParam&0xffff, lParam>>16);    \
  198.             break;                \
  199.         case WM_DISPLAYCHANGE:    \
  200.         case WM_SIZE:            \
  201.             s3MesaResizeWindow(ctxlist[a].s3ctx, lParam&0xffff, lParam>>16);    \
  202.             break;                \
  203.         case WM_ACTIVATE:        \
  204.             /* In fullscreen mode, probably need to do something here */    \
  205.             break;                \
  206.         }    \
  207.     }        \
  208.     return(ctxlist[a].hWNDOldProc(hwnd, message, wParam, lParam));    \
  209. }
  210.  
  211. MONITORPROC( 0);    MONITORPROC( 1); MONITORPROC( 2); MONITORPROC( 3); MONITORPROC( 4);
  212. MONITORPROC( 5);    MONITORPROC( 6); MONITORPROC( 7); MONITORPROC( 8); MONITORPROC( 9);
  213. MONITORPROC(10);    MONITORPROC(11); MONITORPROC(12); MONITORPROC(13); MONITORPROC(14);
  214. MONITORPROC(15);    MONITORPROC(16); MONITORPROC(17); MONITORPROC(18); MONITORPROC(19);
  215. MONITORPROC(20);    MONITORPROC(21); MONITORPROC(22); MONITORPROC(23); MONITORPROC(24);
  216. MONITORPROC(25);    MONITORPROC(26); MONITORPROC(27); MONITORPROC(28); MONITORPROC(29);
  217. MONITORPROC(30);    MONITORPROC(31); MONITORPROC(32);
  218.  
  219. WNDPROC monitorproclist[MAX_CONTEXTS+1] =  {
  220.     __wglMonitor0,  __wglMonitor1,  __wglMonitor2,  __wglMonitor3,  __wglMonitor4,
  221.     __wglMonitor5,  __wglMonitor6,  __wglMonitor7,  __wglMonitor8,  __wglMonitor9,
  222.     __wglMonitor10, __wglMonitor11, __wglMonitor12, __wglMonitor13, __wglMonitor14,
  223.     __wglMonitor15, __wglMonitor16, __wglMonitor17, __wglMonitor18, __wglMonitor19,
  224.     __wglMonitor20, __wglMonitor21, __wglMonitor22, __wglMonitor23, __wglMonitor24,
  225.     __wglMonitor25, __wglMonitor26, __wglMonitor27, __wglMonitor28, __wglMonitor29,
  226.     __wglMonitor30, __wglMonitor31, __wglMonitor32
  227. };
  228.  
  229.  
  230.  
  231. /*
  232.  * CopyContext copies the state from one context to another - not currently supported
  233.  */
  234. _DLLEXPORT_ BOOL APIENTRY wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
  235. {
  236.     return(FALSE);
  237. }
  238.  
  239.  
  240. /*
  241.  * CreateContext - creates an OpenGL rendering context to work onto a Windows DC
  242.  */
  243. _DLLEXPORT_ HGLRC APIENTRY wglCreateContext(HDC hdc)
  244. {
  245.     HWND        hWnd;
  246.     WNDPROC    oldProc;
  247.     int slot;
  248.  
  249.     /* Fail if we have allocated all our contexts */
  250.     if (context_count == MAX_CONTEXTS)
  251.     {
  252.         SetLastError(0);
  253.         return(NULL);
  254.     }
  255.     /* No window; nothing to render on; abort */
  256.     if(!(hWnd = WindowFromDC(hdc)))
  257.     {
  258.         SetLastError(0);
  259.         return(NULL);
  260.     }
  261.     /* A valid pixelformat must have been set into the DC and therefore our driver */
  262.     if(curPFD == 0)
  263.     {
  264.         SetLastError(0);
  265.         return(NULL);
  266.     }
  267.     /* Set up the log */
  268.     fclose(stderr);
  269.     fopen("MESA.LOG","w");
  270.  
  271.     /* Find an empty slot */
  272.     for (slot=1; slot<MAX_CONTEXTS+1; slot++) {
  273.         if (!ctxlist[slot].s3ctx)
  274.             break;
  275.     }
  276.     if (slot == (MAX_CONTEXTS+1)) {
  277.         SetLastError(0);
  278.         return(NULL);
  279.     }
  280.  
  281.     /* Set up our monitoring of the window procedure, to catch any critical Windows messages */
  282.     if ((oldProc = (WNDPROC) GetWindowLong(hWnd, GWL_WNDPROC)) != monitorproclist[slot])
  283.     {
  284.         ctxlist[slot].hWNDOldProc = oldProc;
  285.         SetWindowLong(hWnd, GWL_WNDPROC, (LONG)monitorproclist[slot]);
  286.     }
  287.  
  288.     /* Create the S3Mesa context */
  289.     if(!(ctxlist[slot].s3ctx = s3MesaCreateBestContext((GLuint)hWnd, 0, 0, pix[curPFD - 1].mesaAttr)))
  290.     {
  291.         SetLastError(0);
  292.         return(NULL);
  293.     }
  294.     context_count++;
  295.  
  296.     /* Save our critical internals */
  297.     ctxlist[slot].hDC    = hdc;
  298.     ctxlist[slot].hWND    = hWnd;
  299.  
  300.     /* And... we're off! */
  301.     return((HGLRC) slot);
  302. }
  303.  
  304. /*
  305.  * Layers not supported
  306.  */
  307. _DLLEXPORT_ HGLRC APIENTRY wglCreateLayerContext(HDC hdc,int iLayerPlane)
  308. {
  309.     SetLastError(0);
  310.     return(NULL);
  311. }
  312.  
  313. /*
  314.  * DeleteContext - kill the current context and shut down OpenGL
  315.  */
  316. _DLLEXPORT_ BOOL APIENTRY wglDeleteContext(HGLRC hglrc)
  317. {
  318.     if (((int) hglrc < (MAX_CONTEXTS+1)) && ctxlist[(int) hglrc].s3ctx)
  319.     {
  320.         s3MesaDestroyContext(ctxlist[(int) hglrc].s3ctx);
  321.         ctxlist[(int) hglrc].s3ctx = 0;
  322.         context_count--;
  323.         return(TRUE);
  324.  
  325.         if ((int) hglrc == current_context) {
  326.             current_context = 0;
  327.             ctx = 0;
  328.         }
  329.     }
  330.     SetLastError(0);
  331.     return(FALSE);
  332. }
  333.  
  334. /*
  335.  * GetCurrentContext - return it
  336.  */
  337. _DLLEXPORT_ HGLRC APIENTRY wglGetCurrentContext(VOID)
  338. {
  339.     if (current_context)
  340.         return((HGLRC) current_context);
  341.  
  342.     SetLastError(0);
  343.     return(NULL);
  344. }
  345.  
  346. /*
  347.  * GetCurrentDC - return the DC associated with the rendering context
  348.  */
  349. _DLLEXPORT_ HDC APIENTRY wglGetCurrentDC(VOID)
  350. {
  351.     if (ctx)
  352.         return(ctxlist[current_context].hDC);
  353.  
  354.     SetLastError(0);
  355.     return(NULL);
  356. }
  357.  
  358. /*
  359.  * GetProcAddress - return the address of an appropriate extension
  360.  */
  361. _DLLEXPORT_ PROC APIENTRY wglGetProcAddress(LPCSTR lpszProc)
  362. {
  363.     int        i;
  364.  
  365. #ifdef DEBUG_WGL
  366.     fprintf(stderr, "Attempt to reference extension %s\n", lpszProc);
  367. #endif
  368.  
  369.     for(i = 0;i < qt_ext;i++)
  370.         if(!strcmp(lpszProc,ext[i].name))
  371.             return(ext[i].proc);
  372.  
  373.     SetLastError(0);
  374.     return(NULL);
  375. }
  376.  
  377. /*
  378.  * MakeCurrent - make a particular context the 'current' one
  379.  */
  380. _DLLEXPORT_ BOOL APIENTRY wglMakeCurrent(HDC hdc, HGLRC hglrc)
  381. {
  382.     if (hglrc == 0) {
  383.         ctx = NULL;
  384.         s3MesaMakeCurrent(ctx);
  385.         return(TRUE);
  386.     }
  387.  
  388.     if (((int) hglrc >= (MAX_CONTEXTS+1)) ||
  389.         (ctxlist[(int) hglrc].s3ctx == NULL) ||
  390.         WindowFromDC(hdc) != ctxlist[(int) hglrc].hWND)
  391.     {
  392.         SetLastError(0);
  393.         return(FALSE);
  394.     }
  395.  
  396.     ctxlist[current_context].hDC = hdc;
  397.     ctx = ctxlist[(int) hglrc].s3ctx;
  398.     s3MesaMakeCurrent(ctx);
  399.  
  400.     return(TRUE);
  401. }
  402.  
  403. /*
  404.  * ShareLists - not supported, but return something appropriate in idiot cases
  405.  */
  406. _DLLEXPORT_ BOOL APIENTRY wglShareLists(HGLRC hglrc1,HGLRC hglrc2)
  407. {
  408.     if (hglrc1 != hglrc2)
  409.     {
  410.         SetLastError(0);
  411.         return(FALSE);
  412.     }
  413.     return(TRUE);
  414. }
  415.  
  416.  
  417. /*
  418.  * Font functions: not supported
  419.  */
  420. _DLLEXPORT_ BOOL APIENTRY wglUseFontBitmapsA(HDC hdc,DWORD first,DWORD count,DWORD listBase)
  421. {
  422.     return(FALSE);
  423. }
  424.  
  425. _DLLEXPORT_ BOOL APIENTRY wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase)
  426. {
  427.     return(wglUseFontBitmapsA(hdc, first, count, listBase));
  428. }
  429.  
  430. _DLLEXPORT_ BOOL APIENTRY wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count,
  431.                                           DWORD listBase,FLOAT deviation,
  432.                                           FLOAT extrusion,int format,
  433.                                           LPGLYPHMETRICSFLOAT lpgmf)
  434. {
  435.     SetLastError(0);
  436.     return(FALSE);
  437. }
  438.  
  439. _DLLEXPORT_ BOOL APIENTRY wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count,
  440.                                           DWORD listBase,FLOAT deviation,
  441.                                           FLOAT extrusion,int format,
  442.                                           LPGLYPHMETRICSFLOAT lpgmf)
  443. {
  444.     SetLastError(0);
  445.     return(FALSE);
  446. }
  447.  
  448.  
  449. /*
  450.  * Layers not supported
  451.  */
  452. _DLLEXPORT_ BOOL APIENTRY wglDescribeLayerPlane(HDC hdc,int iPixelFormat,
  453.                                             int iLayerPlane,UINT nBytes,
  454.                                             LPLAYERPLANEDESCRIPTOR plpd)
  455. {
  456.     SetLastError(0);
  457.     return(FALSE);
  458. }
  459.  
  460. _DLLEXPORT_ int APIENTRY wglSetLayerPaletteEntries(HDC hdc,int iLayerPlane,
  461.                                                int iStart,int cEntries,
  462.                                                CONST COLORREF *pcr)
  463. {
  464.  
  465.     fprintf(stderr, "SetLayerPaletteEntries\n");
  466.  
  467.     SetLastError(0);
  468.     return(0);
  469. }
  470.  
  471. _DLLEXPORT_ int APIENTRY wglGetLayerPaletteEntries(HDC hdc,int iLayerPlane,
  472.                                                int iStart,int cEntries,
  473.                                                COLORREF *pcr)
  474. {
  475.     fprintf(stderr, "GetLayerPaletteEntries\n");
  476.  
  477.     SetLastError(0);
  478.     return(0);
  479. }
  480.  
  481. _DLLEXPORT_ BOOL APIENTRY wglRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)
  482. {
  483.     fprintf(stderr, "RealizeLayerPaletteEntries\n");
  484.  
  485.     SetLastError(0);
  486.     return(FALSE);
  487. }
  488.  
  489. _DLLEXPORT_ BOOL APIENTRY wglSwapLayerBuffers(HDC hdc,UINT fuPlanes)
  490. {
  491.     if (ctx &&
  492.         (WindowFromDC(hdc) == ctxlist[current_context].hWND) &&
  493.         (fuPlanes == WGL_SWAP_MAIN_PLANE))
  494.     {
  495.         s3MesaSwapBuffers();
  496.         return(TRUE);
  497.     }
  498.     SetLastError(0);
  499.     return(FALSE);
  500. }
  501.  
  502.  
  503. /* Pixel Format functions */
  504.  
  505. /*
  506.  * ChoosePixelFormat - compare our supported device pixelformats against the one
  507.  * supplied and match as best we can
  508.  */
  509. _DLLEXPORT_ int APIENTRY wglChoosePixelFormat(HDC hdc,
  510.                                             CONST PIXELFORMATDESCRIPTOR *ppfd)
  511. {
  512.     int        i,best = -1,bestdelta = 0x7FFFFFFF,delta;
  513.  
  514.     if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1)
  515.     {
  516.         SetLastError(0);
  517.         return(0);
  518.     }
  519.  
  520.     for(i = 0;i < qt_pix;i++)
  521.     {
  522.         delta = 0;    // 'difference' counter
  523.  
  524.         /* Any of these failing is a critical fail */
  525.         if((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
  526.             continue;
  527.         if((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
  528.             continue;
  529.         if((ppfd->dwFlags & PFD_SUPPORT_GDI) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI))
  530.             continue;
  531.         if((ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
  532.             continue;
  533.         if(!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
  534.              ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
  535.             continue;
  536.         if(!(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
  537.              ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO)))
  538.             continue;
  539.  
  540.         /* These are non-critical fails - match as best we can */
  541.         if(ppfd->iPixelType != pix[i].pfd.iPixelType)
  542.             delta++;
  543.         if (ppfd->cDepthBits != pix[i].pfd.cDepthBits)
  544.             delta++;
  545.  
  546.         /* Is this the best? */
  547.         if(delta < bestdelta)
  548.         {
  549.             best = i + 1;
  550.             bestdelta = delta;
  551.             if(bestdelta == 0)
  552.                 break;
  553.         }
  554.     }
  555.  
  556.     /* not found.... whoops! */
  557.     if(best == -1)
  558.     {
  559.         SetLastError(0);
  560.         return(0);
  561.     }
  562.     return(best);
  563. }
  564.  
  565. /*
  566.  * DescribePixelFormat
  567.  */
  568. _DLLEXPORT_ int APIENTRY wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
  569.                                     LPPIXELFORMATDESCRIPTOR ppfd)
  570. {
  571.     if(iPixelFormat < 1 || iPixelFormat > qt_pix || nBytes != sizeof(PIXELFORMATDESCRIPTOR))
  572.     {
  573.         SetLastError(0);
  574.         return(0);
  575.     }
  576.     *ppfd = pix[iPixelFormat - 1].pfd;
  577.     return(qt_pix);
  578. }
  579.  
  580. /* UNKNOWN !!!
  581. wglGetDefaultProcAddress()
  582. */
  583.  
  584. /*
  585.  * GetPixelFormat
  586.  */
  587. _DLLEXPORT_ int APIENTRY wglGetPixelFormat(HDC hdc)
  588. {
  589.     if(curPFD == 0)
  590.     {
  591.         SetLastError(0);
  592.         return(0);
  593.     }
  594.     return(curPFD);
  595. }
  596.  
  597. /*
  598.  * SetPixelFormat
  599.  */
  600. _DLLEXPORT_ BOOL APIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat,
  601.                                 PIXELFORMATDESCRIPTOR *ppfd)
  602. {
  603.     if(iPixelFormat < 1 || iPixelFormat > qt_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR))
  604.     {
  605.         SetLastError(0);
  606.         return(FALSE);
  607.     }
  608.     curPFD = iPixelFormat;
  609.     return(TRUE);
  610. }
  611.  
  612.  
  613.  
  614. /*
  615.  * Double Buffer call
  616.  */
  617. _DLLEXPORT_ BOOL APIENTRY wglSwapBuffers(HDC hdc)
  618. {
  619.     if(!ctx)
  620.     {
  621.         SetLastError(0);
  622.         return(FALSE);
  623.     }
  624.     s3MesaSwapBuffers();
  625.     return(TRUE);
  626. }
  627.  
  628. #endif /* S3 */
  629.  
  630.